/*
 * Copyright (C) 2018 Tianjin KYLIN Information Technology Co., Ltd.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3, or (at your option)
 * any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, see <http://www.gnu.org/licenses/>.
 *
**/
#include "authdialog.h"

#include <QDebug>
#include <QPixmap>
#include <QHBoxLayout>
#include <QPainter>
#include <QPainterPath>
#include <unistd.h>
#include <pwd.h>
#include <QBitmap>
#include <QFont>
#include <QIcon>

#include "users.h"
#include "iconedit.h"
#include "biometricproxy.h"
#include "biometricauthwidget.h"
#include "biometricdeviceswidget.h"
#include "pam-tally.h"
#include "commonfunc.h"
#include "loginoptionswidget.h"

AuthDialog::AuthDialog(const UserItem &user, QWidget *parent) :
    QWidget(parent),
    user(user),
    auth(new AuthPAM(this)),
    authMode(UNKNOWN),
    m_deviceCount(-1),
    m_biometricProxy(nullptr),
    m_widgetLoginOpts(nullptr),
    m_buttonsWidget(nullptr),
    m_retryButton(nullptr),
    isBioPassed(false),
    m_bioTimer(nullptr),
	m_timer(nullptr),
    isLockingFlg(false),
    m_nCurLockMin(0),
    useFirstDevice(false)
{
    initUI();
    pam_tally_init();  //这里写函数声明

    connect(auth, &Auth::showMessage, this, &AuthDialog::onShowMessage);
    connect(auth, &Auth::showPrompt, this, &AuthDialog::onShowPrompt);
    connect(auth, &Auth::authenticateComplete, this, &AuthDialog::onAuthComplete);

    useFirstDevice = getUseFirstDevice();
    m_failedTimes.clear();
}

void AuthDialog::startAuth()
{
    prompted = false;
    unacknowledged_messages = false;
    auth->authenticate(user.name);

    m_passwordEdit->clear();
    m_passwordEdit->readOnly(true);
}

void AuthDialog::stopAuth()
{
    if(m_widgetLoginOpts)
    {
        if(m_bioTimer && m_bioTimer->isActive())
            m_bioTimer->stop();
        m_widgetLoginOpts->stopAuth();

        m_widgetLoginOpts->hide();
    }   

    clearMessage();
   // auth->stopAuth();
    m_passwordEdit->readOnly(true);
//    if(m_passwdWidget)
//        m_passwdWidget->hide();
}

QPixmap AuthDialog::PixmapToRound(const QPixmap &src, int radius)
{
    if (src.isNull()) {
        return QPixmap();
    }

    QPixmap pixmapa(src);
    QPixmap pixmap(radius*2,radius*2);
    pixmap.fill(Qt::transparent);
    QPainter painter(&pixmap);
    painter.setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform);
    QPainterPath path;
    path.addEllipse(0, 0, radius*2, radius*2);
    painter.setClipPath(path);
    painter.drawPixmap(0, 0, radius*2, radius*2, pixmapa);
    return pixmap;
}

void AuthDialog::initUI()
{
    if (scale < 0.5) {
        setFixedWidth(360);
    } else {
        setFixedWidth(600);
    }

    m_userWidget = new QWidget(this);
    m_userWidget->setObjectName(QStringLiteral("userWidget"));

    /* 头像 */
    const QString SheetStyle = QString("border-radius: %1px;  border:0px   solid white;").arg(77*scale);
    m_labelHeadImg = new QLabel(m_userWidget);
    m_labelHeadImg->setObjectName(QStringLiteral("faceLabel"));
    m_labelHeadImg->setFocusPolicy(Qt::NoFocus);
    m_labelHeadImg->setStyleSheet(SheetStyle);
    m_labelHeadImg->setAlignment(Qt::AlignCenter);
    m_labelHeadImg->hide();

    QPixmap facePixmap(user.icon);
    facePixmap = facePixmap.scaled(154*scale,154*scale, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
    facePixmap = PixmapToRound(facePixmap, 77*scale);
    m_labelHeadImg->setAlignment(Qt::AlignCenter);
    m_labelHeadImg->setPixmap(facePixmap);

    // 人脸识别
    m_labelFace = new QLabel(m_userWidget);
    m_labelFace->setObjectName("faceLabel");
    m_labelFace->setAlignment(Qt::AlignCenter);
    m_labelFace->hide();

    // 二维码窗口
    m_labelLoginTypeTip = new QLabel(m_userWidget);
    //m_labelLoginTypeTip->setStyleSheet("QToolTip{border-radius:4px;background-color:#FFFFFF;color:black;font-size:16px}");
    m_labelLoginTypeTip->setObjectName("loginTypeTipLabel");
    m_labelLoginTypeTip->setAlignment(Qt::AlignCenter);
    QFont font = m_labelLoginTypeTip->font();
    font.setPixelSize(14);
    m_labelLoginTypeTip->setFont(font);
    m_labelQRCode = new QLabel(m_userWidget);
    m_labelQRCode->setObjectName("qrCodeLabel");
    m_labelQRCode->setAlignment(Qt::AlignCenter);
    m_labelQRCode->hide();
    QVBoxLayout *layoutQRCode = new QVBoxLayout();
    layoutQRCode->setAlignment(Qt::AlignCenter);
    layoutQRCode->setSpacing(10);
    m_labelQRCode->setLayout(layoutQRCode);
    m_labelQRCodeTip = new QLabel();
    m_labelQRCodeTip->setFixedSize(22,22);
    m_labelQRCodeTip->setPixmap(QIcon::fromTheme("ukui-dialog-warning").pixmap(QSize(22,22)));
    layoutQRCode->addWidget(m_labelQRCodeTip, 0, Qt::AlignHCenter);
    m_labelQRCodeMsg = new QLabel();
    m_labelQRCodeMsg->setFixedHeight(24);
    font = m_labelQRCodeMsg->font();
    font.setPixelSize(16);
    m_labelQRCodeMsg->setStyleSheet("QLabel{background-color:rgba(255,255,255,0);color:rgb(255,0,0)}");
    m_labelQRCodeMsg->setFont(font);
    layoutQRCode->addWidget(m_labelQRCodeMsg, 0, Qt::AlignHCenter);

    /* 用户名 */
    m_nameLabel = new QLabel(m_userWidget);
    m_nameLabel->setObjectName(QStringLiteral("login_nameLabel"));
    m_nameLabel->setFocusPolicy(Qt::NoFocus);
    m_nameLabel->setAlignment(Qt::AlignCenter);
    m_nameLabel->setStyleSheet("QToolTip{border-radius:4px;background-color:#FFFFFF;color:black;font-size:16px}");
    //m_nameLabel->setText(user.realName.isEmpty() ? user.name : user.realName);
    QString text = user.realName.isEmpty() ? user.name : user.realName;
    font = m_nameLabel->font();
    font.setPixelSize(24);
    QString str = ElideText(font,500,text);
    if(text != str)
         m_nameLabel->setToolTip(text);
    if(text == str)
        m_nameLabel->setToolTip("");
    m_nameLabel->setText(str);


    /* 密码框所在窗口 */
    m_passwdWidget = new QWidget(this);
    m_passwdWidget->setObjectName(QStringLiteral("passwordWidget"));

    /* 密码框 */
    m_passwordEdit = new IconEdit(m_passwdWidget);
    connect(m_passwordEdit,&IconEdit::clickedPassword,
            this,&AuthDialog::onM_passwordEditClicked);

    m_passwdWidget->setInputMethodHints(Qt::ImhNone);
    m_passwordEdit->setObjectName(QStringLiteral("passwordEdit"));
    m_passwordEdit->setIcon(QIcon(":/image/assets/login-button.svg"));
    m_passwordEdit->setFocusPolicy(Qt::StrongFocus);
    m_passwordEdit->installEventFilter(this);
    m_passwordEdit->readOnly(true);
    m_passwordEdit->setType(QLineEdit::Password);
    setFocusProxy(m_passwordEdit);
    connect(m_passwordEdit, SIGNAL(clicked(const QString&)),
            this, SLOT(onRespond(const QString&)));

    //m_passwdWidget->hide();

    /* 密码认证信息显示列表 */
    m_messageLabel = new QLabel(m_passwdWidget);
    m_messageLabel->setObjectName(QStringLiteral("messageLabel"));
    m_messageLabel->setAlignment(Qt::AlignLeft);
    font = m_messageLabel->font();
    font.setPixelSize(14);
    m_messageLabel->setFont(font);
    m_messageLabel->setStyleSheet("QToolTip{border-radius:4px;background-color:#FFFFFF;color:black;font-size:16px}");

    m_messageButton = new QPushButton(m_passwdWidget);
    m_messageButton->setObjectName(QStringLiteral("messageButton"));
    m_messageButton->hide();
}

void AuthDialog::unlock_countdown()
{
    int failed_count = 0;
    int time_left = 0;
    int deny = 0;
    int fail_time =0;
    int unlock_time = 0;
    pam_tally_unlock_time_left(user.uid, &failed_count, &time_left, &deny,&fail_time,&unlock_time);

    // qDebug() << "failed_count:" << failed_count << "time_left:" <<time_left <<"deny:"<<deny<<"fail_time:"<< fail_time<<"unlock_time:" << unlock_time;
    if(time_left >= 60)//请多少分钟后重试
    {
        int nMinuteleft = time_left/60;
        if (isLockingFlg == false){
            m_nCurLockMin = unlock_time/60;//获取当前需要锁定的分钟数
        }

        //如果当前设置的不是1min钟锁定，那么1min显示成2min，由2min直接跳到59s || 剩余分钟数小于当前设置的锁定时间，并且大于1min，自增+1
        if ((nMinuteleft == 1 && m_nCurLockMin != 1)  || (nMinuteleft > 1 && nMinuteleft < m_nCurLockMin))
        {
            nMinuteleft = nMinuteleft + 1;
        }

        m_messageLabel->setText(tr("Please try again in %1 minutes.").arg(nMinuteleft));
        m_messageLabel->setToolTip(tr("Please try again in %1 minutes.").arg(nMinuteleft));
        m_passwordEdit->clearText();
        m_passwordEdit->readOnly(true);
        m_passwordEdit->setLocked(true);
        isLockingFlg = true;
        return ;
    }
    else if(time_left > 0 && time_left < 60)//请多少秒后重试
    {
        m_messageLabel->setText(tr("Please try again in %1 seconds.").arg(time_left%60));
        m_messageLabel->setToolTip(tr("Please try again in %1 seconds.").arg(time_left%60));
        m_passwordEdit->clearText();
        m_passwordEdit->readOnly(true);
        m_passwordEdit->setLocked(true);
        isLockingFlg = true;
        return ;
    }
    else if (failed_count == 0xFFFF)//账号被永久锁定
    {
        m_messageLabel->setText(tr("Account locked permanently."));
        m_messageLabel->setToolTip(tr("Account locked permanently."));
        m_passwordEdit->clearText();
        m_passwordEdit->readOnly(true);
        m_passwordEdit->setLocked(true);
        isLockingFlg = true;
        return ;
    }
    else
    {
        if(m_passwordEdit){
            m_passwordEdit->readOnly(false);
            m_passwordEdit->setFocus();
        }
        if (isLockingFlg)
        {
            onShowMessage("",Auth::MessageTypeError);
            isLockingFlg = false;
            m_passwordEdit->setLocked(false);
        }
            
        m_timer->stop();
    }
    return ;
}

void AuthDialog::root_unlock_countdown()
{
    int failed_count = 0;
    int time_left = 0;
    int deny = 0;
    int fail_time =0;
    int unlock_time = 0;
    pam_tally_root_unlock_time_left(&failed_count, &time_left, &deny,&fail_time,&unlock_time);
    if(time_left >= 60)//请多少分钟后重试
    {
        int nMinuteleft = time_left/60;
        if (isLockingFlg == false){
            m_nCurLockMin = unlock_time/60;//获取当前需要锁定的分钟数
        }


        //如果当前设置的不是1min钟锁定，那么1min显示成2min，由2min直接跳到59s || 剩余分钟数小于当前设置的锁定时间，并且大于1min，自增+1
        if ((nMinuteleft == 1 && m_nCurLockMin != 1)  || (nMinuteleft > 1 && nMinuteleft < m_nCurLockMin))
        {
            nMinuteleft = nMinuteleft + 1;
        }

        m_messageLabel->setText(tr("Please try again in %1 minutes.").arg(nMinuteleft));
        m_messageLabel->setToolTip(tr("Please try again in %1 minutes.").arg(nMinuteleft));
        m_passwordEdit->clearText();
        m_passwordEdit->readOnly(true);
        isLockingFlg = true;
        return ;
    }
    else if(time_left > 0 && time_left < 60)//请多少秒后重试
    {
        m_messageLabel->setText(tr("Please try again in %1 seconds.").arg(time_left%60));
        m_messageLabel->setToolTip(tr("Please try again in %1 seconds.").arg(time_left%60));
        m_passwordEdit->clearText();
        m_passwordEdit->readOnly(true);
        isLockingFlg = true;
        return ;
    }
    else if (failed_count == 0xFFFF)//账号被永久锁定
    {
        m_messageLabel->setText(tr("Account locked permanently."));
        m_messageLabel->setToolTip(tr("Account locked permanently."));
        m_passwordEdit->clearText();
        m_passwordEdit->readOnly(true);
        isLockingFlg = true;
        return ;
    }
    else
    {
        if(m_passwordEdit){
            m_passwordEdit->readOnly(false);
            m_passwordEdit->setFocus();
        }
        if (isLockingFlg)
        {
            onShowMessage("",Auth::MessageTypeError);
            isLockingFlg = false;
        }
            
        m_timer->stop();
    }
    return ;
}

void AuthDialog::resizeEvent(QResizeEvent *)
{
    setChildrenGeometry();
}

void AuthDialog::setChildrenGeometry()
{
    if(scale < 0.5)
        setFixedWidth(500);
    // 用户信息显示位置
    m_userWidget->setGeometry(0, 0,
                              width(), 376*scale);
    m_labelLoginTypeTip->setGeometry(0,0,m_userWidget->width(), 24);
    m_labelLoginTypeTip->setAlignment(Qt::AlignCenter);
    m_labelHeadImg->setStyleSheet(QString("border-radius: %1px;  border:0px   solid white;").arg(77*scale));
    m_labelHeadImg->setGeometry((width() - 154*scale) / 2 , m_labelLoginTypeTip->geometry().bottom()+24*scale, 154*scale, 154*scale);
    QPixmap facePixmap(user.icon);
    facePixmap = facePixmap.scaled(154*scale,154*scale, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
    facePixmap = PixmapToRound(facePixmap, 77*scale);
    m_labelHeadImg->setPixmap(facePixmap);

    m_labelQRCode->setStyleSheet(QString("border-radius: %1px;  border:0px solid white;background-color: rgba(255,255,255,100%);").arg(6*scale));
    m_labelQRCode->setGeometry((width() - 154*scale) / 2 , m_labelLoginTypeTip->geometry().bottom()+24*scale, 154*scale, 154*scale);
    setQRCode(m_imgQRCode);

    m_labelFace->setStyleSheet(QString("border-radius: %1px;  border:0px solid white;background-color: rgba(255,255,255,10%);").arg(77*scale));
    m_labelFace->setGeometry((width() - 154*scale) / 2 , m_labelLoginTypeTip->geometry().bottom()+24*scale, 154*scale, 154*scale);
    QImage faceImg;
    setFaceImg(faceImg);

    m_nameLabel->setGeometry(0, m_labelHeadImg->geometry().bottom() + 16*scale,
                             width(), 34);

    m_passwdWidget->setGeometry(0, m_nameLabel->geometry().bottom() + 24*scale, width(), 100);
    m_passwordEdit->setGeometry((m_passwdWidget->width() - 240)/2, 0, 240, 40);
    m_messageLabel->setGeometry((m_passwdWidget->width() - 240)/2,
                                m_passwordEdit->geometry().bottom() + 4,
                                width()-(m_passwdWidget->width() - 240)/2, 20);

    m_messageButton->setGeometry((m_passwdWidget->width() - 200)/2, 0, 200, 40);

    setBiometricWidgetGeometry();
}

void AuthDialog::switchLoginOptType(unsigned uLoginOptType)
{
    switch(uLoginOptType) {
    case LOGINOPT_TYPE_PASSWORD:
    {
        m_labelHeadImg->show();
        m_labelQRCode->hide();
        m_labelFace->hide();
    }
        break;
    case LOGINOPT_TYPE_FACE:
    {
        m_labelHeadImg->hide();
        m_labelQRCode->hide();
        m_labelFace->show();
    }
        break;
    case LOGINOPT_TYPE_FINGERPRINT:
    case LOGINOPT_TYPE_VOICEPRINT:
    case LOGINOPT_TYPE_FINGERVEIN:
    case LOGINOPT_TYPE_IRIS:
    {
        m_labelHeadImg->show();
        m_labelQRCode->hide();
        m_labelFace->hide();
    }
        break;
    case LOGINOPT_TYPE_QRCODE:
    {
        m_labelHeadImg->hide();
        setQRCodeMsg("");
        m_labelQRCode->show();
        m_labelFace->hide();
    }
        break;
    default:
        return;
    }
    if (uLoginOptType != m_uCurLoginOptType || (m_deviceInfo && m_deviceInfo->id != m_nLastDeviceId)) {
        clearMessage();
        switch(uLoginOptType) {
        case LOGINOPT_TYPE_PASSWORD:
        {
            setLoginTypeTip("");
        }
            break;
        case LOGINOPT_TYPE_FACE:
        {
            setLoginTypeTip(tr("Verify face recognition or enter password to unlock"));
        }
            break;
        case LOGINOPT_TYPE_FINGERPRINT:
        {
            setLoginTypeTip(tr("Press fingerprint or enter password to unlock"));
        }
            break;
        case LOGINOPT_TYPE_VOICEPRINT:
        {
            setLoginTypeTip(tr("Verify voiceprint or enter password to unlock"));
        }
            break;
        case LOGINOPT_TYPE_FINGERVEIN:
        {
            setLoginTypeTip(tr("Verify finger vein or enter password to unlock"));
        }
            break;
        case LOGINOPT_TYPE_IRIS:
        {
            setLoginTypeTip(tr("Verify iris or enter password to unlock"));
        }
            break;
        case LOGINOPT_TYPE_QRCODE:
        {
            setLoginTypeTip(tr("Use the bound wechat scanning code or enter the password to unlock"));
        }
            break;
        default:
            return;
        }
    }
    if (m_deviceInfo) {
        m_nLastDeviceId = m_deviceInfo->id;
    } else {
        m_nLastDeviceId = -1;
    }

    m_uCurLoginOptType = uLoginOptType;
}


void AuthDialog::closeEvent(QCloseEvent *event)
{
    qDebug() << "AuthDialog::closeEvent";

    if(auth && auth->isAuthenticating())
    {
        auth->stopAuth();
    }

    //调用kylin的接口，重新初始化
    QDBusInterface interface("com.kylin.network",
                                  "/com/kylin/network",
                                  "com.kylin.network",
                                  QDBusConnection::sessionBus());
    QDBusMessage result = interface.call("keyRingInit");

    return QWidget::closeEvent(event);
}


void AuthDialog::onShowMessage(const QString &message, Auth::MessageType type)
{
    qDebug()<<message;
    //qDebug() << "onShowMessage" << message;
    //设置label最小高度
    m_messageLabel->setMinimumHeight(36);
    if (message.indexOf("account locked") != -1 || message.indexOf("账户已锁定") != -1 
        || message.indexOf("Account locked") != -1 || message.indexOf("永久锁定") != -1)
    {
        if(!m_timer){
            m_timer = new QTimer(this);
            m_timer->setInterval(800);
            connect(m_timer, &QTimer::timeout, this, &AuthDialog::unlock_countdown);
        }
        m_timer->start();
    }else if (message.indexOf("No password received, please input password") != -1){
        m_messageLabel->setText(tr("Password cannot be empty"));
        m_messageLabel->setToolTip(tr("Password cannot be empty"));
    }
    else{
        QString strText = message;
        if (!m_preStrMessage.isEmpty() && m_preStrMessageType != type && m_preStrMessageType != -1)
        {
            strText = m_preStrMessage + "," + strText;
        }
        QFontMetrics font(m_messageLabel->font());
        QString strDisplay = font.elidedText(message, Qt::ElideRight, m_messageLabel->width()-8);
        m_messageLabel->setText(strDisplay);
        m_messageLabel->setToolTip(message);
    }
     unacknowledged_messages = true; 
    //stopWaiting();
}

void AuthDialog::pamBioSuccess()
{
    m_bioTimer->stop();
    if (!m_widgetLoginOpts) {
        switchLoginOptType(LOGINOPT_TYPE_PASSWORD);
        return ;
    }
    m_widgetLoginOpts->startAuth(m_deviceInfo, user.uid);
    if (m_deviceInfo) {
        switchLoginOptType(m_widgetLoginOpts->convertDeviceType(m_deviceInfo->deviceType));
    } else {
        switchLoginOptType(LOGINOPT_TYPE_PASSWORD);
    }
}

void AuthDialog::startBioAuth(unsigned uTimeout)
{
    if (m_widgetLoginOpts)
        m_widgetLoginOpts->stopAuth();
    if(!m_bioTimer){
        m_bioTimer = new QTimer(this);
        connect(m_bioTimer, SIGNAL(timeout()), this, SLOT(pamBioSuccess()));
    }
    m_bioTimer->start(uTimeout);

}

void AuthDialog::setX11Focus()
{
    if(m_passwordEdit && m_passwordEdit->isVisible()){
    	m_passwordEdit->setX11Focus();
    }
}

void AuthDialog::onShowPrompt(const QString &prompt, Auth::PromptType type)
{
    qDebug() << "-------prompt: " << prompt;
    QString text = prompt;

    if(text == BIOMETRIC_PAM || text == BIOMETRIC_PAM_DOUBLE || text == BIOMETRIC_PAM_QRCODE) {
        if(isBioPassed){
            onRespond(BIOMETRIC_SUCCESS);
            return ;
        }
        if(authMode == PASSWORD) {
            skipBiometricAuth();
        } else {
            performBiometricAuth();
        }
    } else {
        stopWaiting();
        if(!text.isEmpty()) {
            m_passwordEdit->readOnly(false);
            m_passwordEdit->show();
        }

        m_passwordEdit->setFocus();
        
        prompted = true;
        unacknowledged_messages = false;
        m_preStrMessage = "";
        if (!m_deviceInfo) {
            switchLoginOptType(LOGINOPT_TYPE_PASSWORD);
        }

        if(text == "Password: " || text == "密码："){
            text = tr("Password ");
        } else if (text == "Input password" || text == "Input Password" || text == "输入密码") {
            text = tr("Input Password");
        }

        m_passwordEdit->clear();
        m_passwordEdit->setPrompt(text);
        m_passwordEdit->show();
        if(!m_timer){
            m_timer = new QTimer(this);
            m_timer->setInterval(200);
            connect(m_timer, &QTimer::timeout, this, &AuthDialog::unlock_countdown);
        }
        m_timer->start();        
    }
}

void AuthDialog::onAuthComplete()
{
    stopWaiting();
    qDebug()<<"--------------------"<<auth->isAuthenticated();
    if(auth->isAuthenticated()) {
        if (m_widgetLoginOpts) {
            m_widgetLoginOpts->stopAuth();
        }
       
        if((prompted && !unacknowledged_messages )||direct_login) {
            direct_login = false;
            Q_EMIT authenticateCompete(true);
        } else {
            qDebug()<<"prompted  = "<<prompted<<"  unacknowledged_messages = "<<unacknowledged_messages;
            prompted = true;
            show_authenticated ();
        }
    } else {
	   //因为有个概率性会认证失败的问题，导致重试按钮显示出来，因此这里暂时屏蔽
//        if (prompted)
//        {
            if(m_messageLabel->text()=="")
                onShowMessage(tr("Authentication failure, Please try again"),
                      Auth::MessageTypeError);
            authMode = PASSWORD;
            startAuth();
//	}
//	else
//	{
//            show_authenticated (false);	
//	}
    }
}

void AuthDialog::show_authenticated(bool successful)
{
    m_passwdWidget->show();
    m_passwordEdit->hide();
    m_messageButton->show();
    m_messageButton->setFocus();
    m_messageButton->setDefault(true);
    
    connect(m_messageButton, &QPushButton::clicked,
            this, &AuthDialog::onMessageButtonClicked);
    if(successful)
    {
        isretry = false;
        m_messageButton->setText(tr("Login"));
        switchLoginOptType(LOGINOPT_TYPE_PASSWORD);
    }
    else
    {
        isretry = true;
        m_messageButton->setText(tr("Retry"));
    }

}

void AuthDialog::onMessageButtonClicked()
{
    m_messageButton->setDefault(false);
    if(!isretry)
    { 
        Q_EMIT authenticateCompete(true);
    }
    else
    {
        m_messageButton->hide();
        authMode = PASSWORD;

        m_messageLabel->setText("");
        startAuth();
    }
}

void AuthDialog::onRespond(const QString &text)
{
    unacknowledged_messages=false;
    clearMessage();
    startWaiting();
    m_passwordEdit->readOnly(true);
    auth->respond(text);
}

void AuthDialog::onM_passwordEditClicked()
{
    Q_EMIT clickPassword(true);
}

//void AuthDialog::onCapsLockChanged()
//{
//    m_passwordEdit->onCapsStateChanged();
//}

void AuthDialog::startWaiting()
{
    if(m_buttonsWidget)
    {
        m_buttonsWidget->setEnabled(false);
    }
}

void AuthDialog::stopWaiting()
{
    m_passwordEdit->stopWaiting();
    if(m_buttonsWidget)
    {
        m_buttonsWidget->setEnabled(true);
    }
}

void AuthDialog::clearMessage()
{
    m_messageLabel->clear();
    m_preStrMessage = "";
    m_preStrMessageType = -1;
}

void AuthDialog::performBiometricAuth()
{
    if(!m_biometricProxy)
    {
        m_biometricProxy = new BiometricProxy(this);
        isHiddenSwitchButton = GetHiddenSwitchButton();
        maxFailedTimes = GetFailedTimes();
    }

    //服务没启动，或者打开DBus连接出错
    if(!m_biometricProxy->isValid())
    {
        qWarning() << "An error occurs when connect to the biometric DBus";
        skipBiometricAuth();
        if (m_deviceInfo) {
            if (!m_widgetLoginOpts || !m_widgetLoginOpts->findDeviceById(m_deviceInfo->id)
                || m_widgetLoginOpts->isDeviceDisable(m_deviceInfo->id)) {
                m_deviceInfo = DeviceInfoPtr();
            }
        }
        return;
    }

    //初始化生物识别认证UI
    initBiometricWidget();

    //初始化enableBiometriAuth
    if(m_deviceCount <= 0)
    {
        m_deviceCount = m_widgetLoginOpts->getLoginOptCount();
    }

    //没有可用设备，不启用生物识别认证
    if(m_deviceCount < 1)
    {
        qWarning() << "No available devices";
        skipBiometricAuth();
        return;
    }

    //获取默认设备
    if(m_deviceName.isEmpty())
    {
        m_deviceName = GetDefaultDevice(user.name);
    }
    qDebug() << m_deviceName;
    if (m_deviceInfo) {
        if (!m_widgetLoginOpts || !m_widgetLoginOpts->findDeviceById(m_deviceInfo->id)
            || m_widgetLoginOpts->isDeviceDisable(m_deviceInfo->id)) {
            m_deviceInfo = DeviceInfoPtr();
        }
    }

    //如果默认设备为空的话，第一次不启动生物识别认证
    if(m_deviceName.isEmpty() && !m_deviceInfo)
    {
        if(useFirstDevice == true) {
            m_deviceInfo = m_widgetLoginOpts->getFirstDevInfo();
        } else {
            skipBiometricAuth();
            return;
        }
    }

    //clearMessage();

    if(!m_deviceInfo)
    {
        m_deviceInfo = m_widgetLoginOpts->findDeviceByName(m_deviceName);
        if (!m_deviceInfo)
            m_deviceInfo = m_widgetLoginOpts->getFirstDevInfo();
    }
    if(!m_deviceInfo)
    {
        skipBiometricAuth();
        return;
    }
    switchLoginOptType(m_widgetLoginOpts->convertDeviceType(m_deviceInfo->deviceType));
    startBioAuth();
    skipBiometricAuth();
}

void AuthDialog::skipBiometricAuth()
{
    auth->respond(BIOMETRIC_IGNORE);
}

void AuthDialog::initBiometricWidget()
{
    if(m_widgetLoginOpts) {
        m_widgetLoginOpts->setUser(user.uid);
    } else {
        m_widgetLoginOpts = new LoginOptionsWidget(m_biometricProxy, user.uid, this);
        connect(m_widgetLoginOpts, &LoginOptionsWidget::authComplete,
                this, &AuthDialog::onBiometricAuthComplete);
        connect(m_widgetLoginOpts, &LoginOptionsWidget::optionSelected,
                this, &AuthDialog::onDeviceChanged);
        connect(m_widgetLoginOpts, &LoginOptionsWidget::updateImage,
                this, &AuthDialog::onLoginOptImage);
        connect(m_widgetLoginOpts, &LoginOptionsWidget::notifyOptionsChange,
                this, &AuthDialog::onLoginOptsCount);
        connect(m_widgetLoginOpts, &LoginOptionsWidget::updateAuthMsg,
                this, &AuthDialog::setLoginMsg);
    }

    qDebug()<<"----------DeviceCount:"<<m_widgetLoginOpts->getLoginOptCount();
    if (m_widgetLoginOpts->getLoginOptCount() < 1)
        m_widgetLoginOpts->hide();
    else
        m_widgetLoginOpts->show();
    m_widgetLoginOpts->setEnabled(true);

    setBiometricWidgetGeometry();
}

void AuthDialog::setBiometricWidgetGeometry()
{
    //生物识别
    if(m_widgetLoginOpts)
    {
        m_widgetLoginOpts->setGeometry(0, m_passwdWidget->geometry().bottom(),
                                           width(), 84*scale);
        qDebug()<<"LoginOptGeometry:"<<m_widgetLoginOpts->geometry()<<","<<m_passwdWidget->geometry()
               <<","<<geometry()<<",isHidden:"<<m_widgetLoginOpts->isHidden();
    }
}

void AuthDialog::onDeviceChanged(unsigned uCurLoginOptType, const DeviceInfoPtr &deviceInfo)
{
    if (!deviceInfo)
        return;
    qDebug() << "device changed: " << *deviceInfo;
    if(m_failedTimes.contains(deviceInfo->id) &&
        m_failedTimes[deviceInfo->id]  >= maxFailedTimes){
        qDebug() << "Failed MAX:"<<deviceInfo->id;
        return ;
    }
    if (deviceInfo == m_deviceInfo) {
        return ;
    }
    m_deviceInfo = deviceInfo;
    switchLoginOptType(uCurLoginOptType);
    if(!isBioPassed)
        startBioAuth();
}

void AuthDialog::onBiometricAuthComplete(bool result, int nStatus)
{
    if(!result) {
        if (nStatus >= 2) {
            if (m_deviceInfo) {
                if (m_failedTimes.contains(m_deviceInfo->id)) {
                    m_failedTimes[m_deviceInfo->id] = m_failedTimes[m_deviceInfo->id] + 1;
                } else {
                    m_failedTimes[m_deviceInfo->id] = 1;
                }
                qDebug()<<"Failed count:"<<m_failedTimes[m_deviceInfo->id]<<",Max:"<<maxFailedTimes<<",id:"<<m_deviceInfo->id;
                if (m_deviceInfo->deviceType == DeviceType::Face) {
                    QImage imgFailed;
                    setFaceImg(imgFailed, 1);
                }
                if(m_failedTimes[m_deviceInfo->id] >= maxFailedTimes){
                    if (m_deviceInfo->deviceType == REMOTE_QRCODE_TYPE) {
                        setLoginTypeTip(tr("Failed to verify %1, please enter password to unlock").arg(DeviceType::getDeviceType_tr(m_deviceInfo->deviceType)));
                        QImage nullImage;
                        setQRCode(nullImage);
                    } else {
                        setLoginTypeTip(tr("Unable to verify %1, please enter password to unlock").arg(DeviceType::getDeviceType_tr(m_deviceInfo->deviceType)));
                    }
                    if (m_widgetLoginOpts)
                        m_widgetLoginOpts->setDeviceDisable(m_deviceInfo->id, true);
                    return ;
                }
                setLoginTypeTip(tr("Failed to verify %1, you still have %2 verification opportunities")
                                .arg(DeviceType::getDeviceType_tr(m_deviceInfo->deviceType))
                                .arg(maxFailedTimes-m_failedTimes[m_deviceInfo->id]));
            }
        }

        if(!isBioPassed) {
            if (nStatus <= 0) {
                qDebug()<<"Biometric dbus error:"<<nStatus;
            }
            if (m_uCurLoginOptType == LOGINOPT_TYPE_QRCODE && nStatus == 1) {
                setQRCodeMsg(tr("NET Exception"));
                startBioAuth(10000);
            } else {
                startBioAuth();
            }
            if (nStatus >= 2 && m_deviceInfo) {
                if (m_deviceInfo->deviceType == DeviceType::Face) {
                    QImage imgFailed;
                    setFaceImg(imgFailed, 1);
                }
            }
        }
    } else {
        direct_login = true;
        isBioPassed = true;
        onBiometricButtonClicked();
    }
}

void AuthDialog::onBiometricButtonClicked()
{
    //当前没有设备
    if (!m_deviceInfo) {
        qWarning()<<"未选择生物设备--";
        return ;
    }
    authMode = BIOMETRIC;
    startAuth();
}

void AuthDialog::onPasswordButtonClicked()
{
    skipBiometricAuth();
}

void AuthDialog::onOtherDevicesButtonClicked()
{
    if (m_widgetLoginOpts)
        m_widgetLoginOpts->stopAuth();
}

void AuthDialog::onRetryButtonClicked()
{
    if (m_widgetLoginOpts)
        m_widgetLoginOpts->startAuth(m_deviceInfo, user.uid);
    //m_retryButton->setVisible(false);
}

void AuthDialog::setQRCode(QImage& imgQRCode)
{
    if (imgQRCode.isNull()) {
        m_imgQRCode.load(":/image/assets/ukui-qrcode-null.svg");
    } else {
        m_imgQRCode = imgQRCode;
    }
    m_imgQRCode = m_imgQRCode.scaled(QSize(150*scale, 150*scale));
    m_labelQRCode->setAlignment(Qt::AlignCenter);
    m_labelQRCode->setPixmap(QPixmap::fromImage(m_imgQRCode));
}

void AuthDialog::setQRCodeMsg(QString strMsg)
{
    if (strMsg.isEmpty()) {
        m_labelQRCodeMsg->hide();
        m_labelQRCodeTip->hide();
    } else {
        m_labelQRCodeMsg->setText(strMsg);
        m_labelQRCodeMsg->show();
        m_labelQRCodeTip->show();
    }
}

void AuthDialog::setFaceImg(QImage& imgFace, int nStatus)
{
    QPixmap faceImage;
    m_labelFace->setFixedSize(154*scale,154*scale);
    //如果头像文件不存在，则使用默认头像
    if(!imgFace.isNull()) {
        faceImage = PixmapToRound(QPixmap::fromImage(imgFace),77*scale);
    } else {
        switch(nStatus){
        case 1:
            faceImage = QPixmap(":/image/assets/ukui-loginopt-lose.svg");
            break;
        default:
            faceImage = QPixmap(":/image/assets/ukui-loginopt-smile.svg");
            break;
        }
    }

    m_labelFace->setAlignment(Qt::AlignCenter);
    m_labelFace->setPixmap(faceImage);
}

void AuthDialog::setLoginTypeTip(QString strLoginTypeTip)
{
    m_strLoginTypeTip = strLoginTypeTip;
    if (!m_strLoginTypeTip.isEmpty()) {
        QFontMetrics font(m_labelLoginTypeTip->font());
        QString strDisplay = font.elidedText(m_strLoginTypeTip, Qt::ElideRight, m_messageLabel->width()-8);
        m_labelLoginTypeTip->setText(strDisplay);
        m_labelLoginTypeTip->setToolTip(m_strLoginTypeTip);
        m_labelLoginTypeTip->show();
    } else {
        m_labelLoginTypeTip->hide();
    }
}

void AuthDialog::setLoginMsg(QString strLoginMsg)
{
    setLoginTypeTip(strLoginMsg);
}

void AuthDialog::onLoginOptsCount(unsigned uCount)
{
    qDebug()<<"----------------------onLoginOptsCount Count:"<<uCount;
    if (!m_widgetLoginOpts)
        return ;
    if (uCount > 0) {
        setBiometricWidgetGeometry();
        m_widgetLoginOpts->show();
    } else {
        switchLoginOptType(LOGINOPT_TYPE_PASSWORD);
        m_widgetLoginOpts->hide();
    }

    if (!m_deviceInfo || !m_widgetLoginOpts->findDeviceById(m_deviceInfo->id)
        || m_widgetLoginOpts->isDeviceDisable(m_deviceInfo->id)) {
        m_widgetLoginOpts->stopAuth();
        authMode = BIOMETRIC;
        startAuth();
    }
}

void AuthDialog::onLoginOptImage(QImage img)
{
//    if (img.isNull()) {
//        return ;
//    }
    if (m_uCurLoginOptType == LOGINOPT_TYPE_FACE) {
        setFaceImg(img);
    } else if (m_uCurLoginOptType == LOGINOPT_TYPE_QRCODE) {
        setQRCode(img);
    }
}
